package com.robert.BCH;

public class preCompute {
    /**
     * 这个是预计算的相关函数，在这里预计算出后面所需要的结果
     * genPoly是利用极小多项式构造出来的生成多项式集合
     * distGen是生成多项式的下界，与生成多项式对应
     * msgBits是明文消息的比特数
     */
    private polynomial[] genPoly;
    private int[] distGen;
    private int[] msgBits;
    private alpha alp;
    private cyclotomic cyc;

    public void precomputeAll(parameters p){
        computeAlpha(p);
        computeCyclotomic(p);
        computeDistGen(cyc);
        computeGenPoly(p,alp,cyc);
        computeMsgBits(p);
    }

    //下面的函数除了getter，其余的在调试后改为private即可

    /**
     * 计算生成多项式
     * @param p 公共参数
     * @param a alpha
     * @param c 分圆域
     */
    private void computeGenPoly(parameters p, alpha a, cyclotomic c){
        genPoly = new polynomial[c.getCycSet().size()];
        polynomial tp = new polynomial("1");
        minPoly mp = new minPoly();
        for(int i=0;i<genPoly.length;i++){
            int[] poly = mp.minPolynomial(p,a,c.getCycSet().get(i));
            tp = tp.multiply(new polynomial(poly));
            genPoly[i] = tp;
        }
    }

    /**
     * 计算生成多项式的汉明距离
     * @param c 分圆域
     */
    private void computeDistGen(cyclotomic c){
        distGen = new int[c.getCycSet().size()];
        for(int i=0;i<distGen.length;i++){
            //minC分圆陪集中最小的元素，即为第一个元素
            int minC = c.getCycSet().get(i).get(0);
            for(int j=minC;j<c.getAuxiliary().length;j++){
                if(c.getAuxiliary()[j]>minC){
                    distGen[i] = j+1;
                    break;
                }
            }
        }
        //还有一个汉明距离为码长
        distGen[distGen.length-1] = c.getAuxiliary().length+1;
    }

    /**
     * 计算明文比特数
     * @param p 公共参数
     */
    private void computeMsgBits(parameters p){
        if(genPoly==null) return;
        msgBits = new int[genPoly.length];
        //由循环码的生成多项式可以得出，也可以由多项式相乘需要得到一个deg为n的多项式得出
        for(int i=0;i<genPoly.length;i++){
            msgBits[i] = p.getN() - genPoly[i].getDeg();
        }
    }

    /**
     * 计算alpha
     * @param p 公共参数
     */
    private void computeAlpha(parameters p){
        alp = new alpha();
        alp.computeAlpha(p);
    }

    /**
     * 计算分圆域
     * @param p 公共参数
     */
    private void computeCyclotomic(parameters p){
        cyc = new cyclotomic();
        cyc.computeCycSet(p);
    }

    public polynomial[] getGenPoly() {
        return genPoly;
    }

    public int[] getDistGen() {
        return distGen;
    }

    public int[] getMsgBits() {
        return msgBits;
    }

    public alpha getAlpha() {
        return alp;
    }

    public cyclotomic getCyclotomic() {
        return cyc;
    }
}
